package KuangShen.ZhuJieHeFanShe;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/*
Java采用泛型擦除的机制引入泛型，Java中的泛型仅仅是给编译器javac使用的，确保数据的安全性和免去强制类型转换问题，
但是，一旦编译完成，所有的泛型有关的类型全部擦除。

为了通过反射操作这些泛型，Java新增了ParameterizedType(意为参数化的类型)，GenericArrayType(意为一般的数组类型)，
TypeVariable(意为类型变量),WildcardType(意为通配符类型)几种类型来代表不能被归一到Class类中的类型，但是又和原始类型齐名的类型

ParameterizedType(意为参数化的类型)--------表示一种参数化类型，比如Collection<String>
GenericArrayType(意为一般的数组类型)-------表示一种元素类型是参数化类型或者一种元素类型是类型变量的数组类型
TypeVariable(意为类型变量)----------------是各种类型变量的公共父接口
WildcardType(意为通配符类型)--------------代表一种通配符类型表达式

getGenericExceptionTypes();---------获取泛型的异常信息
getGenericParameterTypes();---------获取泛型的参数信息
getGenericParameterTypes();---------获取泛型的返回值信息
 */
//通过反射获取泛型
public class test11 {

    public void test01 (Map<String,User> map ,List<User> list ){ //泛型作为参数
        System.out.println("test01");
    }


    public Map<String,User> test02(){  //泛型作为返回值
        System.out.println("test02");
        return null;
    }


    //获取方法test01的参数信息
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = test11.class.getMethod("test01", Map.class, List.class);                 //通过类名创建Class对象，通过反射获取指定的方法叫”test01“
        Type[] genericParameterTypes = method.getGenericParameterTypes();                              //通过反射所获取的方法，获取该方法的参数类型并放入一个数组
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("指定方法的参数信息#"+genericParameterType);                                //可以看到#所指的就是指定方法的参数信息，一个Map，一个List


            //进一步取出泛型Map和泛型List的信息
            if(genericParameterType instanceof ParameterizedType){                                     //判断泛型的的参数类型(即Map和List参数类型)是否是参数化类型（结构化参数类型）
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); //进行强制类型转换，获取泛型Map或List的真实参数信息并放入一个数组
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("Map或List的真实参数信息----"+actualTypeArgument);                   //打印结果
                }
            }

        }


        //获取方法test02的返回值信息
        method = test11.class.getMethod("test02", null);                                 //反射获取的指定方法”test02“重新赋值给method
        Type genericReturnType = method.getGenericReturnType();                                               //获取返回值类型
        if(genericReturnType instanceof ParameterizedType){                                                   //判断test02的返回值类型是否是参数化类型（结构化参数类型）
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();   //进行强制类型转换，获取返回值（泛型类）的真实参数信息并放入一个数组
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("当泛型作为返回值的真实参数信息----"+actualTypeArgument);                           //打印结果
            }
        }


    }





}
